//
// Created by WenDaoJiang on 2017/6/19.
// Copyright (c) 2017 文道江. All rights reserved.
//

#import "AgoraPlugin.h"
#import "CallVideoViewController.h"

@implementation AgoraPlugin {
    NSDictionary *loginInfo;
    SocketIO *mSocket;
    BOOL isBackground;
    HybridEventBus *eventBus;
    NSDictionary *eventMap;
    NSDictionary *AgoraConfig;
    NSDictionary *connectParams;
    BOOL calling;
    int netStatus;
}
- (instancetype)init {
    self = [super init];
    if (self) {
        [self initializeAgora];
    }
    return self;
}

- (void)initializeAgora {

    eventBus = [HybridEventBus defaultEventBus];
    eventMap = @{
            @"callUser": @"agora_signal_on_call",
            @"endVideoChat": @"agora_signal_on_end_call",
            @"callUserFail": @"agora_signal_on_call_fail",
            @"callUserSuccess": @"agora_signal_on_call_success",
            @"signal_event_customize": @"agora_signal_event_customize",
            @"videoChat": @"agora_signal_in_video_chat",
    };

    NSDictionary *agora_signal_login_info = [KVStorage getJsonValue:@"agora_signal_login_info"];
    if (agora_signal_login_info != nil) {
        loginInfo = agora_signal_login_info;
    }

    // 读取配置信息
    AgoraConfig = [[HybridBridge defaultHybridBridge] appInfo][@"Agora"];
    if (IS_DEBUG){
        NSDictionary *AgoraDebugConfig = [HybridBridge defaultHybridBridge].appInfo[@"AgoraDebug"];
        if (AgoraDebugConfig != nil)AgoraConfig = AgoraDebugConfig;
    }

    NSURL *url = [NSURL URLWithString:AgoraConfig[@"SignalServer"]];

    connectParams = @{
            @"app_id": AgoraConfig[@"SignalAppId"]
    };
    mSocket = [[SocketIO alloc] initWithDelegate:self host:url.host port:[url.port integerValue] namespace:nil timeout:10000 secured:NO];
    //[mSocket connectWithParams: connectParams];
    [self connect: 2]; //延迟2秒后连接


    // 收到呼叫
    [eventBus subscribe:@"agora_signal_on_call" UsingBlock:^(NSNotification *notification) {
        calling = YES;
        [self performSelectorOnMainThread:@selector(openCallVideoDelay:) withObject:notification.userInfo waitUntilDone:NO];
    }];

    // 收到结束
    [eventBus subscribe:@"agora_signal_on_end_call" UsingBlock:^(NSNotification *notification) {
        calling = NO;
        dispatch_async(dispatch_get_main_queue(), ^{
            [self dispatchEvent:@"endCall" data:notification.userInfo];
        });
    }];

    // 呼叫失败
    [eventBus subscribe:@"agora_signal_on_call_fail" UsingBlock:^(NSNotification *notification) {
        dispatch_async(dispatch_get_main_queue(), ^{
            NSInteger code = notification.userInfo != nil && notification.userInfo[@"code"] != nil ? [notification.userInfo[@"code"] integerValue] : 0;
            [self dispatchEvent:@"callFail" data: @(code)];
        });
    }];

    // 呼叫成功
    [eventBus subscribe:@"agora_signal_on_call_success" UsingBlock:^(NSNotification *notification) {
        NSMutableDictionary *data = [NSMutableDictionary dictionaryWithDictionary:notification.userInfo];
        data[@"isCall"] = @(YES);
        calling = YES;
        [self performSelectorOnMainThread:@selector(openCallVideoDelay:) withObject:data waitUntilDone:NO];
    }];

    /* 本地触发的事件 */

    // 登录
    [eventBus subscribe:@"agora_signal_login" UsingBlock:^(NSNotification *notification) {
        loginInfo = [NSDictionary dictionaryWithDictionary:notification.userInfo];
        NSLog(@"agora_signal_login notification %@", notification.userInfo);
        [self login];
    }];

    // 退出
    [eventBus subscribe:@"agora_signal_logout" UsingBlock:^(NSNotification *notification) {
        loginInfo = nil;
        [self logout];
    }];

    // 挂断
    [eventBus subscribe:@"signal_emit_end_call" UsingBlock:^(NSNotification *notification) {
        [self emit:@"endCall" Data:notification.userInfo];
        dispatch_async(dispatch_get_main_queue(), ^{
            //本地挂断时同样触发
            [self dispatchEvent:@"endCall" data:notification.userInfo];
        });
    }];

    // 接通
    [eventBus subscribe:@"signal_emit_accept_call" UsingBlock:^(NSNotification *notification) {
        [self emit:@"acceptCall" Data:notification.userInfo];
    }];

    // 发起呼叫
    [eventBus subscribe:@"local_call_user" UsingBlock:^(NSNotification *notification) {
        NSDictionary *callInfo = notification.userInfo;
        if(callInfo == nil || loginInfo == nil || loginInfo[@"uid"] == nil)return;
        NSInteger toUid = [callInfo[@"toUid"] integerValue];
        [self emit:@"callUser" Data:@{
                @"toUid": @(toUid),
                @"extData": callInfo,
                @"fromUid": loginInfo[@"uid"]
        }];
    }];

    // 本地发起其他event
    [eventBus subscribe:@"local_event_customize" UsingBlock:^(NSNotification *notification) {
        NSDictionary *event = notification.userInfo;
        if(event != nil && event[@"eventName"] != nil && event[@"data"] != nil){
            [self emit:@"signal_event_customize" Data:event];
        }
    }];

    /* 网络状态监听 */
    [eventBus subscribe:@"networkChanged" UsingBlock:^(NSNotification *notification) {
        NSLog(@"networkChanged: 0 :%@", notification.userInfo);
        netStatus = [notification.userInfo[@"status"] integerValue];
        if(mSocket != nil){
            dispatch_async(dispatch_get_main_queue(), ^() {
                if(netStatus > 0){
                    [self connect: 4];
                }else{
                    [mSocket disconnect];
                }
            });
        }
    }];
}

- (void)connect:(int)delay {
    if (connectParams != nil && !mSocket.isConnected && !mSocket.isConnecting && netStatus > 0) {
        [mSocket performSelector:@selector(connectWithParams:) withObject:connectParams afterDelay:delay];
    }
}

-(void)openCallVideoDelay:(NSDictionary *)callInfo {
    [self performSelector:@selector(openCallVideo:) withObject:callInfo afterDelay: 1];
}

- (void)openCallVideo:(NSDictionary *)callInfo {
    if(!calling || callInfo == nil || callInfo[@"created_at"] == nil || callInfo[@"timeout"] == nil)return;

    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
    dateFormatter.dateFormat = @"yyyy-MM-dd HH:mm:ss";
    NSDate *createAt = [dateFormatter dateFromString: callInfo[@"created_at"]];

    NSDate *timeout = [NSDate dateWithTimeIntervalSinceNow: 0];

    NSTimeInterval interval = [timeout timeIntervalSinceDate: createAt];

    // 检测是否过期
    if(interval < [callInfo[@"timeout"] integerValue]){
        dispatch_async(dispatch_get_main_queue(), ^{
            CallVideoViewController *viewController = [[CallVideoViewController alloc] init];
            viewController.callInfo = callInfo;
            viewController.appID = AgoraConfig[@"AgoraAppId"];
            if(self.controller.navigationController != nil){
                [self.controller.navigationController pushViewController:viewController animated:NO];
            }else{
                [self.controller presentViewController:viewController animated:NO completion:nil];
            }
        });
    }
}

- (void)login {
    if (loginInfo != nil && loginInfo[@"uid"] != nil && loginInfo[@"userType"] != nil) {

        NSString *deviceToken = [KVStorage getValue:@"push_registry_credentials"];
        NSDictionary *params = @{
                @"uid": loginInfo[@"uid"],
                @"type": loginInfo[@"userType"],
                @"active": @(!isBackground),
                @"deviceToken": deviceToken == nil ? @"" : deviceToken
        };

        [self emit:@"login" Data:params];
    }
}

- (void)logout {
    [self emit:@"logout" Data:@{}];
}

- (void)changeState:(BOOL)active {
    [self emit:@"changeState" Data:@{@"active": @(active)}];
}

- (void)emit:(NSString *)eventName Data:(NSDictionary *)data {
    if (mSocket != nil && mSocket.isConnected) {
        [mSocket sendEvent:eventName data:data];
    }
}


// plugin Delegate

- (void)enterBackground {
    isBackground = YES;
    [self changeState:NO];
}

- (void)enterForeground {
    isBackground = NO;
    if(netStatus > 0){
        if(connectParams != nil && !mSocket.isConnected && !mSocket.isConnecting){
            [mSocket performSelector:@selector(connectWithParams:) withObject:connectParams afterDelay: 1];
        }else {
            [self changeState:YES];
        }
    }
}

- (void)didBecomeActive {
    isBackground = NO;
}

// socket io Delegate

- (void)socketIODidConnect:(SocketIO *)socket {
    NSLog(@"socketIO socketIODidConnect");
    NSLog(@"deviceToken: %@", [KVStorage getValue:@"push_registry_credentials"]);
    [self performSelector:@selector(login) withObject:nil afterDelay:1];
}


- (void)socketIO:(SocketIO *)socket didReceiveEvent:(NSString *)eventName data:(id)data extradata:(id)extradata ack:(SocketIOCallback)function {
    NSLog(@"eventName: %@, data: %@", eventName, data);

    if ([@"callUserSuccess" isEqualToString:eventName]){
        data[@"isCall"] = @(YES);
    }

    if(eventBus != nil && eventMap[eventName] != nil){
        [eventBus postData:data Tag:eventMap[eventName]];
    }
}

- (void)socketIODidDisconnect:(SocketIO *)socket {
    [self connect: 5];
    NSLog(@"socketIODidDisconnect");
    // 断开连接就10秒后触发socket已断开广播
    [self performSelector:@selector(triggerSocketIODidDisconnect) withObject:nil afterDelay:10];
}

- (void)socketIO:(SocketIO *)socket didReceiveError:(NSString *)error {
    NSLog(@"socketIO didReceiveError %@", error);
}

- (void)socketIO:(SocketIO *)socket didReceiveStream:(SocketIOInputStream *)stream {
    NSLog(@"socketIO didReceiveStream %@", stream);
}

- (void)socketIO:(SocketIO *)socket didReceiveMessage:(id)data ack:(SocketIOCallback)function {
    NSLog(@"socketIO didReceiveMessage %@", data);
}

- (void)triggerSocketIODidDisconnect {
    // 检查一下网络是否已恢复
    if(netStatus <= 0){
        [eventBus postData:@{} Tag:@"socketIODidDisconnect"];
    }
}
@end